/**
 * @文件:    flexible_button.h
 * @作者:    MurphyZhao
 * @日期:    2018-09-29
 * 
 * 版权所有 (c) 2018-2019 MurphyZhao <d2014zjt@163.com>
 *               https://github.com/murphyzhao
 * 保留所有权利.
 * 许可证标识符: Apache-2.0
 *
 * 根据 Apache 许可证 2.0 版（“许可证”）获得许可；
 * 除非符合许可证，否则您不得使用此文件。
 * 您可以在以下网址获取许可证副本：
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * 除非适用法律要求或书面同意，软件按“原样”分发，
 * 不附带任何明示或暗示的担保或条件。
 * 有关许可证下权限和限制的具体语言，请参见许可证。
 *
 * 变更日志:
 * 日期         作者         说明
 * 2018-09-29   MurphyZhao   首次添加
 * 2019-08-02   MurphyZhao   迁移代码到 murphyzhao 仓库
 * 
*/

#ifndef __FLEXIBLE_BUTTON_H__
#define __FLEXIBLE_BUTTON_H__

#include "stdint.h"
#include "string.h"

typedef void (*flex_button_response_callback)(void*);

typedef enum
{
    FLEX_BTN_PRESS_DOWN = 0,           // 按键按下
    FLEX_BTN_PRESS_CLICK,              // 单击
    FLEX_BTN_PRESS_DOUBLE_CLICK,       // 双击
    FLEX_BTN_PRESS_SHORT_START,        // 短按开始
    FLEX_BTN_PRESS_SHORT_UP,           // 短按释放
    FLEX_BTN_PRESS_LONG_START,         // 长按开始
    FLEX_BTN_PRESS_LONG_UP,            // 长按释放
    FLEX_BTN_PRESS_LONG_HOLD,          // 长按保持
    FLEX_BTN_PRESS_LONG_HOLD_UP,       // 长按保持释放
    FLEX_BTN_PRESS_MAX,                // 最大事件数
    FLEX_BTN_PRESS_NONE,               // 无事件
} flex_button_event_t;

/**
 * flex_button_t
 * 
 * @简介 按键数据结构体
 *        下面的成员需要用户在扫描前初始化。
 * 
 * @成员 pressed_logic_level:    按键按下时的电平。必须在调用 'flex_button_register' API 前初始化。
 * @成员 debounce_tick:          按键消抖时间，单位为扫描周期数。
 * @成员 click_start_tick:       单击起始时间，单位为扫描周期数。
 * @成员 short_press_start_tick: 短按起始时间，单位为扫描周期数。
 * @成员 long_press_start_tick:  长按起始时间，单位为扫描周期数。
 * @成员 long_hold_start_tick:   长按保持起始时间，单位为扫描周期数。
 * @成员 usr_button_read:        读取指定按键的电平值的函数指针。
 * @成员 cb:                     按键事件回调函数。如果使用 'flex_button_event_read' API，可以不初始化 cb 成员。
 * @成员 next :                  下一个按键结构体指针
*/
typedef struct flex_button
{
    uint8_t pressed_logic_level : 1; /* 需要用户初始化 */

    /**
     * @event
     * 按键事件，取值为 flex_button_event_t 枚举列表中的值。
     * 由 'flex_button_register' API 自动初始化为默认值 FLEX_BTN_PRESS_NONE。
    */
    uint8_t event               : 4;

    /**
     * @status
     * 用于记录按键状态。
     * 由 'flex_button_register' API 自动初始化为默认值 0。
    */
    uint8_t status              : 3;
    uint16_t scan_cnt;  /* 默认0。用于记录按键扫描次数 */
    uint16_t click_cnt; /* 默认0。用于记录按键点击次数 */

    uint16_t debounce_tick;          
    uint16_t click_start_tick;
    uint16_t short_press_start_tick;
    uint16_t long_press_start_tick;
    uint16_t long_hold_start_tick;

    uint8_t  (*usr_button_read)(void);
    flex_button_response_callback  cb;
    struct flex_button* next;
} flex_button_t;

#ifdef __cplusplus
extern "C" {
#endif

int8_t flex_button_register(flex_button_t *button);
flex_button_event_t flex_button_event_read(flex_button_t* button);
void flex_button_scan(void);

#ifdef __cplusplus
}
#endif  
#endif /* __FLEXIBLE_BUTTON_H__ */
